package cn.ac.iscas.domain;

import cn.ac.iscas.base.enums.TaskStatus;
import cn.ac.iscas.base.log.SchedulerLogger;
import cn.ac.iscas.base.utils.SpringUtil;
import cn.ac.iscas.service.task.INodeTask;
import com.google.common.collect.Sets;
import org.springframework.stereotype.Component;


import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

/**
 * @Author: 
 * @Description: 任务信息，不同类型的任务需各自实现
 * @Date: 2020/6/11
 */
//@Data
//@NoArgsConstructor
//@AllArgsConstructor
@Component
public abstract class NodeTask implements Callable<Map<String, Object>>, INodeTask {

    private SchedulerLogger logger = SpringUtil.getBean(SchedulerLogger.class);
    private String jobId;
    private String taskId;
    //依赖的nodeTask id
    private Set<String> dependences = Sets.newConcurrentHashSet();
    //当前Task运行状态
    private TaskStatus taskStatus = TaskStatus.init;
    //执行结果
    private Map<String, Object> result;
    //开始时间
    private long startTime;
    //结束时间
    private long endTime;
    //耗时
    private long takeTime;
    //任务类型 TODO
    private String type;
    //task元数据：可以是Json或其他  TODO
    private Map<String, Object> metadata;
    //元数据解析器 TODO
    private String metadataParserKey;
    //最长运行时间, -1:表示无时间限制 TODO
    private long maxRuntimeInSec = -1;

    public NodeTask() {

    }

    public NodeTask(String taskId) {
        this.taskId = taskId;
    }

    /**
     * @param taskId      nodeTaskId
     * @param dependences 依赖
     */
    public NodeTask(String jobId, String taskId, Set<String> dependences) {
        this.jobId = jobId;
        this.taskId = taskId;
        this.dependences = dependences;
    }

    public NodeTask(String taskId, Set<String> dependences, String type, Map<String, Object> metadata) {
        this.taskId = taskId;
        this.dependences = dependences;
        this.type = type;
        this.metadata = metadata;
    }

    /**
     * 多线程调度，子类需覆盖此方法
     *
     * @throws Exception
     */
    @Override
    public Map<String, Object> call() throws Exception {
        this.startTime = System.currentTimeMillis();
        logger.getLogger(jobId).info("begin to run task: {}, timestamp: {}", this.taskId, startTime);
        this.result = doTask();
        this.endTime = System.currentTimeMillis();
        this.takeTime = endTime - startTime;
        logger.getLogger(jobId).info("finish task: {}, timestamp: {}, cost time: {}ms", this.taskId, endTime, takeTime);
        return result;
    }

    public SchedulerLogger getLogger() {
        return logger;
    }

    public void setLogger(SchedulerLogger logger) {
        this.logger = logger;
    }

    public String getJobId() {
        return jobId;
    }

    public void setJobId(String jobId) {
        this.jobId = jobId;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public Set<String> getDependences() {
        return dependences;
    }

    public void setDependences(Set<String> dependences) {
        this.dependences = dependences;
    }

    public TaskStatus getTaskStatus() {
        return taskStatus;
    }

    public void setTaskStatus(TaskStatus taskStatus) {
        this.taskStatus = taskStatus;
    }

    public Map<String, Object> getResult() {
        return result;
    }

    public void setResult(Map<String, Object> result) {
        this.result = result;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }

    public long getEndTime() {
        return endTime;
    }

    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }

    public long getTakeTime() {
        return takeTime;
    }

    public void setTakeTime(long takeTime) {
        this.takeTime = takeTime;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Map<String, Object> getMetadata() {
        return metadata;
    }

    public void setMetadata(Map<String, Object> metadata) {
        this.metadata = metadata;
    }

    public String getMetadataParserKey() {
        return metadataParserKey;
    }

    public void setMetadataParserKey(String metadataParserKey) {
        this.metadataParserKey = metadataParserKey;
    }

    public long getMaxRuntimeInSec() {
        return maxRuntimeInSec;
    }

    public void setMaxRuntimeInSec(long maxRuntimeInSec) {
        this.maxRuntimeInSec = maxRuntimeInSec;
    }
}
